const {src,dest,parallel,series, watch} = require('gulp');

// 处理以下任务：
//  一. 处理src目录下的开发文件
//    01. scss --> css
//    02. es2015(+)  ---> es5
//    03. html模板解析
//    04. 图片和字体文件压缩
// 二. 处理public下的文件
//    01. extra任务
//    02. 清除dist目录



// 三. 自动加载插件，无需手动require    yarn add gulp-load-plugins -D
// 四. 配置开发服务器 - 热更新功能 yarn add browser-sync -D



// 五.监视src中文件的变化，变化后，进行构建 - 出发dist文件变化，最终实现页面刷新


// 六. useref 文件引用处理: yarn add gulp-useref -D
//  build以后，html文件中还是存在 /node_modules的引用路径
//  解决：html文件写注释： 将href的路径文件，打包到注释中的路径下
//  <!-- build:css assets/styles/vendor.css -->
//  <link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css">
//  <!-- endbuild -->
//  <!-- build:css assets/styles/main.css -->
//  <link rel="stylesheet" href="assets/styles/main.css">
//  <!-- endbuild -->

// 自动加载插件，无需手动require
const loadPlugins = require('gulp-load-plugins');
const plugins = loadPlugins();

const sass = require('gulp-sass')(require('sass'));// 不能变!!!!!!!!!!!!!!!!!!!!!


// plugins.sass
// scss --> css  yarn add gulp-sass -D

// plugins.babel
// es2015(+)  ---> es5  yarn add gulp-babel @babel/core @babel/preset-env -D

// plugins.swig
// html模板解析  yarn add gulp-swig -D

// plugins.imagemin
// 图片和字体文件压缩  yarn add gulp-imagemin -D

// 删除操作  yarn add del -D
const del = require('del');

/**
 * 删除文件任务
 */
const clean = ()=>{
  // del(['dist']); // 返回一个Promise对象
  return del(['dist']);
};

/**
 * 处理样式任务
 */
const style = ()=>{
  return src('src/assets/styles/*.scss',{base:'src'}) //按照src目录的层级关系来放置复制好的文件
    .pipe(sass({outputStyle:'expanded'}))// 将转换后的css文件中代码的结束大括号单独一行
    .pipe(dest('dist'))
    // .pipe(bs.reload({stream: true})) //最后更新浏览器
};

/**
 * 处理脚本任务
 * @returns {*}
 */
const script = ()=>{
  return src('src/assets/scripts/*.js',{base:'src'})
    .pipe(plugins.babel({presets:['@babel/preset-env']}))
    .pipe(dest('dist'))
};


const data = {
  menus: [
    {
      name: 'Home',
      icon: 'aperture',
      link: 'index.html'
    },
    {
      name: 'Features',
      link: 'features.html'
    },
    {
      name: 'About',
      link: 'about.html'
    },
    {
      name: 'Contact',
      link: '#',
      children: [
        {
          name: 'Twitter',
          link: 'https://twitter.com/w_zce'
        },
        {
          name: 'About',
          link: 'https://weibo.com/zceme'
        },
        {
          name: 'divider'
        },
        {
          name: 'About',
          link: 'https://github.com/zce'
        }
      ]
    }
  ],
  pkg: require('./package.json'),
  date: new Date()
};
/**
 * 处理html文件
 * @returns {*}
 */
const page = ()=>{
  return src('src/*.html') // src/**/*.html  src任意子目录下的html文件
    .pipe(plugins.swig({ data, defaults: { cache: false } })) // 防止模板缓存导致页面不能及时更新
    .pipe(dest('dist'))
};

/**
 * 压缩并拷贝图片文件
 * @returns {*}
 */
const image = ()=>{
  return src('src/assets/images/**',{base:'src'})
    .pipe(plugins.imagemin())
    .pipe(dest('dist'))
};

/**
 * 压缩并拷贝字体文件
 * @returns {*}
 */
const font = ()=>{
  return src('src/assets/fonts/**',{base:'src'})
    .pipe(plugins.imagemin())
    .pipe(dest('dist'))
};

/**
 * 处理public下的文件，其实就是拷贝到dist中
 * @returns {*}
 */
const extra = ()=>{
  return src('public/**',{base:'public'})
    .pipe(dest('dist'))
};

const useref = ()=>{
  return src('dist/*.html',{base:'dist'})
    .pipe(plugins.useref({searchPath:['dist','.']}))
    .pipe(plugins.if(/\.js$/, plugins.uglify())) // 压缩js - 中间产物
    .pipe(plugins.if(/\.html$/, plugins.htmlmin({
      collapseWhitespace: true,
      minifyCSS: true,
      minifyJS: true
    }))) // 压缩html- 中间产物
    .pipe(plugins.if(/\.css$/, plugins.cleanCss())) // 压缩css - 中间产物
    .pipe(dest('release'))
};

// 启动服务器的任务
const browserSync = require('browser-sync');
const bs = browserSync.create();
/**
 * 启动服务器的任务
 */
const serve = ()=>{
  watch('src/assets/styles/*.scss', style); // 监视文件，一旦变化，就执行style任务
  watch('src/assets/scripts/*.js', script);
  watch('src/*.html', page);
  // watch('src/assets/images/**', image); //低效 - 上线之前处理即可
  // watch('src/assets/fonts/**', font); //低效 - 上线之前处理即可
  // watch('public/**', extra); //低效 - 上线之前处理即可
  // 开发过程中，以下三个文件发生变化，自动执行刷新浏览器并请求资源
  watch([
    'src/assets/images/**',
    'src/assets/fonts/**',
    'public/**'
  ],bs.reload);
  bs.init({
    notify: false, // 管理插件在页面上预览时的提示
    port:3001,// 默认3000
    open: true, //执行后可以自动打开浏览器
    files:'dist/**', // 此时dist目录中一旦文件修改，就会出发浏览器更新
    server:{
      baseDir:['dist','src','public'],// 网页根目录 - 依次查找dist，找不到就去src中找，再找不到，就去public中找（解决了以上三个watch低效）
      // 路由先在routes中找文件，最后再去dist中找
      routes:{
        '/node_modules':'node_modules', // 映射到【项目】中的node_modules文件
      }
    }
  })
};

// 处理src下的文件
const compile = parallel(style,script,page);

// 同时处理src和public下的文件 - 上线之前执行该任务
const build = series(clean, parallel(compile, extra,image, font));

const develop = series(compile, serve); //串行

module.exports = {
  build, develop, clean, compile, useref
};
